import { debug } from 'util'

var path = require('path')
var fs = require('fs')
var readline = require('readline') // 按行读取
const util = require('util')
// const execFile = util.promisify(require('child_process').execFile); //返回一个Promise用于Object与stdout和stderr性质
const { exec, execFile } = require('child_process') // 普通引用
const { shell } = require('electron')

/**
 * 读取路径信息
 * @param {string} path 路径
 */
function getStat (path) {
  return new Promise((resolve, reject) => {
    fs.stat(path, (err, stats) => {
      if (err) {
        resolve(false)
      } else {
        resolve(stats)
      }
    })
  })
}

/**
 * 创建路径
 * @param {string} dir 路径
 */
function mkdir (dir) {
  return new Promise((resolve, reject) => {
    fs.mkdir(dir, err => {
      if (err) {
        resolve(false)
      } else {
        resolve(true)
      }
    })
  })
}

/**
 * 路径是否存在，不存在则创建
 * @param {string} dir 路径
 */
async function dirExists (dir) {
  let isExists = await getStat(dir)
  // 如果该路径且不是文件，返回true
  if (isExists && isExists.isDirectory()) {
    return true
  } else if (isExists) { // 如果该路径存在但是文件，返回false
    return false
  }
  // 如果该路径不存在
  let tempDir = path.parse(dir).dir // 拿到上级路径
  // 递归判断，如果上级目录也不存在，则会代码会在此处继续循环执行，直到目录存在
  let status = await dirExists(tempDir)
  let mkdirStatus
  if (status) {
    mkdirStatus = await mkdir(dir)
  }
  return mkdirStattus
}

// 用于测试创建路径 fn(".\\2022\\a\\b\\a.json");
// export async function fn(path) {
//     let index1 = path.lastIndexOf("/");
//     let index2 = path.lastIndexOf("\\");
//     let dir = path.slice(0, index1 == -1 ? index2 : index1);
//     console.log(index1, index2)
//     await dirExists(dir);
//     fs.writeFile(path, '好好学习天天向上', err => {
//         if (err) return console.log(err);
//         console.log('写入成功')
//     })
// }

// 打开文件管理器对应路径
export function openPath (path) {
  shell.openExternal(path)
}

// 运行文件
export function runExe (path, param) {
  // console.log("命令是：", path + " " + param)
  return new Promise((resolve, reject) => {
    exec(path + ' ' + param, { maxBuffer: 20000 * 1024 }, (error, stdout, stderr) => {
      if (error) {
        // console.error(`exec error: ${error}`);
        reject(error)
        return
      }
      resolve({ out: stdout, err: stderr })
      // console.log(`stdout: ${stdout}`);
      // console.error(`stderr: ${stderr}`);
    })
  })
}
// 测试成功源代码
// const { exec } = require("child_process");
// exec("doc\\packtool\\Main.exe", (error, stdout, stderr) => {
//   if (error) {
//     console.error(`exec error: ${error}`);
//     return;
//   }
//   console.log(`stdout: ${stdout}`);
//   console.error(`stderr: ${stderr}`);
// });

// 运行执行文件
export function runExeFile (path, param) {
  // child_process.execFile()函数类似于child_process.exec()
  // 默认情况下它不会生成shell。相反，指定的可执行文件file直接作为一个新进程生成，使其效率略高child_process.exec()
  // child_process.exec()支持的选项相同。由于未生成shell，因此不支持I / O重定向和文件通配等行为
  return new Promise((resolve, reject) => {
    execFile(path, param,
      {
        timeout: 1000, // <number> Default: 0
        encoding: 'utf8', // <string> Default: 'utf8'
        maxBuffer: 20000 * 1024, // <number> stdout或stderr上允许的最大字节数（以字节为单位）。如果超出，则终止子进程并截断任何输出。Default: 1024 * 1024
        windowsHide: false, // <boolean>隐藏通常在Windows系统上创建的子进程控制台窗口。Default: false
        windowsVerbatimArguments: false, // <boolean>在Windows上没有引用或转义参数。在Unix上被忽略了。Default: false
        shell: false // <boolean> | <string>如果true，command在shell内部运行。使用 '/bin/sh'在Unix和process.env.ComSpecWindows上。可以将不同的shell指定为字符串。请参阅Shell要求和 默认Windows Shell。默认值:( false无shell）
      },
      (error, stdout, stderr) => { // 进程终止时用输出调用 error <错误>  stdout <string> | <缓冲:子进程的标准输出>  stderr <string> | <缓冲:标准错误输出>
        if (error) {
          reject(error)
          return false
        }
        resolve({ out: stdout, err: stderr })
        // console.log("error", error);
        // console.log("stdout", stdout);
        // console.log("stderr", stderr);
      }
    ) // 返回：<ChildProcess>
  })

  // 以下是添加监听
  // child.stdout.on('data', function (data) { console.log('stdout: ' + data); });
  // child.stderr.on('data', function (data) { console.log('stderr: ' + data); });
}

// 创/写文件
export async function writeFile (path, content) {
  let index1 = path.lastIndexOf('/')
  let index2 = path.lastIndexOf('\\')
  let dir = path.slice(0, index1 == -1 ? index2 : index1)
  await dirExists(dir)
  return new Promise((resolve, reject) => {
    if (typeof (content) !== 'string') { content = JSON.stringify(content) }
    fs.writeFile(path, content, 'utf8', function (error) {
      if (error) {
        reject(error)
        return false
      }
      resolve({ ok: 0, msg: '写入成功', data: content })
    })
  })
}

// 追加文件
export function appendFile (path, content) {
  if (typeof (content) !== 'string') { content = JSON.stringify(content) }
  fs.appendFile(path, content, function (error) {
    if (error) {
      console.log(error)
      return false
    }
    // console.log('写入成功');
  })
}

// 读文件
export async function readFile (path) {
  let index1 = path.lastIndexOf('/')
  let index2 = path.lastIndexOf('\\')
  let dir = path.slice(0, index1 == -1 ? index2 : index1)
  await dirExists(dir)
  return new Promise((resolve, reject) => {
    fs.readFile(path, function (error, data) {
      if (error) {
        writeFile(path, '').then(() => {
          return readFile(path)
        })
        // reject(error)
        // return false;
      }
      // console.log(data);  //data是读取的十六进制的数据。  也可以在参数中加入编码格式"utf8"来解决十六进制的问题;
      // console.log(data.toString());  //读取出所有行的信息
      // resolve(data.toString())
      resolve(data ? data.toString() : '')
    })
  })
}

// 监听文件内容更新
export function watchFileContent (path, fn) {
  writeFile(path, '').then(() => {
    var filename = path
    var logsArr = new Array()
    sendHisLogs(filename, listenLogs)
    function listenLogs (filePath) {
      console.log('日志监听中...')
      var fileOPFlag = 'a+'
      fs.open(filePath, fileOPFlag, function (error, fd) {
        var buffer
        var remainder = null
        fs.watchFile(filePath, { persistent: true, interval: 100 }, function (
          curr,
          prev
        ) {
          // console.log(curr);
          if (curr.size - prev.size) { // curr.mtime > prev.mtime
            // 文件内容有变化，那么通知相应的进程可以执行相关操作。例如读物文件写入数据库等
            buffer = new Buffer(curr.size - prev.size)
            fs.read(fd, buffer, 0, curr.size - prev.size, prev.size, function (
              err,
              bytesRead,
              buffer
            ) {
              generateTxt(buffer.toString())
            })
          } else {
            console.log('文件读取错误')
          }
        })

        function generateTxt (str) {
          // 处理新增内容的地方
          var temp = str.split('\r\n')
          // console.log("这里", temp)
          for (var s in temp) {
            // console.log(temp[s]);
            if (fn && temp[s]) fn(temp[s])
          }
        }
      })
    };
    function sendHisLogs (filename, listenLogs) {
      var rl = readline.createInterface({
        input: fs.createReadStream(filename, { enconding: 'utf8' }),
        output: null,
        terminal: false // 这个参数很重要
      })

      rl.on('line', function (line) {
        if (line) {
          logsArr.push(line.toString())
        }
      }).on('close', function () {
        for (var i = 0; i < logsArr.length; i++) {
          console.log('发送历史信号: ' + logsArr[i])
        }
        listenLogs(filename)
      })
    };
  })
}
